Load the libraries.
library(data.table)
Registered S3 method overwritten by 'data.table':
method from
print.data.table
data.table 1.12.2 using 4 threads (see ?getDTthreads). Latest news: r-datatable.com
library(ggplot2)
The code below will show the data cleaning and exploration.
First load the data.
Data Wrangling
setwd("C:/Users/Ferhat/Documents/GitHub/WorldBankData")
The working directory was changed to C:/Users/Ferhat/Documents/GitHub/WorldBankData inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.
data = read.csv("MBSComtrade.csv")
data$series_type = NULL
data$table_type = NULL
data$table_type_desc = NULL
data$period_type = NULL
data$trade_flow = NULL
data$currency_type = NULL
data$value_unit = NULL
data$value_type = NULL
data$value_type_desc = NULL
data$base_year = NULL
data$period_number = NULL
data$country_type = NULL
data$estimation_type = NULL
data$estimation_type_desc = NULL
save(data, file = "cleaned_data.rdata")
data = as.data.table(data)
Lets explore some of the data.
head(data[country_english_name == "USA"],10)
Lets do some plots. But first lets get rid of world regions and only keep countryes so we don’t double count. Lets look at the USA first.
USA = data[country_english_name == "USA" & partner_country_code > 0 & partner_country_code < 899 ]
head(USA,10)
Now lets group everything by partner export country.
USA_group = USA[, .(value.SUM = sum(value)), by=c("partner_country_english_name", "year")]
setnames(USA_group, c("Country","Year", "TotalValue") )
head(USA_group,10)
Now lets plot.
Line chart
library(plotly)
Attaching package: 㤼㸱plotly㤼㸲
The following object is masked from 㤼㸱package:ggplot2㤼㸲:
last_plot
The following object is masked from 㤼㸱package:stats㤼㸲:
filter
The following object is masked from 㤼㸱package:graphics㤼㸲:
layout
p = ggplot(USA_group, aes(x = Year, y=TotalValue))+
geom_line(aes(colour = Country))+
geom_point(aes(colour = Country), size=2)+
theme(legend.position="none")
ggplotly(p)
Pie chart
rr ggplot(USA_group, aes(x=factor(1), fill = factor(Country)))+ geom_bar(aes(weight = TotalValue), width = 1)+ coord_polar(theta = , start=0)+ theme(legend.position=)

Sankey Diagram
USA_group_country = USA_group[, .(Sum = sum(TotalValue)), by=Country]
USA_group_country$Source = "USA"
USA_group_country[, Country:=as.character(Country)]
USA_group_country <- USA_group_country %>%
select(Country, Source, Sum)
setorder(USA_group_country, Sum)
slice = tail(USA_group_country, 10)
slice <- slice %>%
select(Source, Country, Sum)
library(googleVis)
Creating a generic function for 㤼㸱toJSON㤼㸲 from package 㤼㸱jsonlite㤼㸲 in package 㤼㸱googleVis㤼㸲
Welcome to googleVis version 0.6.4
Please read Google’s Terms of Use before you start using the package: https://developers.google.com/terms/
Note, the plot method of googleVis will by default use the standard browser to display its output.
See the googleVis package vignettes for more details, or visit https://github.com/mages/googleVis.
To suppress this message use: suppressPackageStartupMessages(library(googleVis))
sk1 <- gvisSankey(slice, from="Source", to="Country", weight="Sum")
print(sk1, 'chart')
Lets play with leaflet package.
Leaflet
library(leaflet)
m <- leaflet() %>% setView(lng = -71.0589, lat = 42.3601, zoom = 12)
m %>% addTiles()
Lets get the latitude and longitude of countries.
rr countries = read.csv(.csv) countries = as.data.table(countries) setnames(countries, old = c(, ), new = c(, ))
head(countries,10)
Now lets populate USA_group data table the latitude and longitude of the countries.
USA_group_joined = merge(USA_group, countries, by = "Country")
na.omit(USA_group_joined)
head(USA_group_joined, 10)
setorder(USA_group_joined, Country, Year)
leaflet(USA_group_joined[USA_group_joined[,Year == 2010]]) %>% addTiles() %>%
addCircles(lng = ~longitude, lat = ~latitude, weight = 1,
radius = ~sqrt(TotalValue), popup = ~paste(Country,"Volume: ",TotalValue), fillOpacity = 0.5
)
Now lets look at the flows using Leaflet’s addflows function.
leaflet(USA_group_joined[USA_group_joined[,Year == 2010]]) %>% addTiles() %>%
addCircles(lng = ~longitude, lat = ~latitude, weight = 1,
radius = ~sqrt(TotalValue), popup = ~paste(Country,"Volume: ",TotalValue), fillOpacity = 0.5
) %>%
leaflet.minicharts::addFlows(countries$longitude[countries$Country == "United States"], countries$latitude[countries$Country == "United States"],
countries$longitude[countries$Country == "Brazil"], countries$latitude[countries$Country == "Brazil"], color = 'green',
flow = USA_group_joined[USA_group_joined[,Year == 2010 & Country == "Brazil"]]$TotalValue, opacity = 0.5) %>%
leaflet.minicharts::addFlows(countries$longitude[countries$Country == "United States"], countries$latitude[countries$Country == "United States"],
countries$longitude[countries$Country == "China"], countries$latitude[countries$Country == "China"], color = 'red',
flow = USA_group_joined[USA_group_joined[,Year == 2010 & Country == "China"]]$TotalValue, opacity = 0.5) %>%
leaflet.minicharts::addFlows(countries$longitude[countries$Country == "United States"], countries$latitude[countries$Country == "United States"],
countries$longitude[countries$Country == "Australia"], countries$latitude[countries$Country == "Australia"], color = 'orange',
flow = USA_group_joined[USA_group_joined[,Year == 2010 & Country == "Australia"]]$TotalValue, opacity = 0.5)
NA
NA
Lets do it with time
leaflet(USA_group_joined) %>% addTiles() %>%
leaflet.minicharts::addFlows(countries$longitude[countries$Country == "United States"], countries$latitude[countries$Country == "United States"],
countries$longitude[countries$Country == "Brazil"], countries$latitude[countries$Country == "Brazil"], color = 'green',
flow = USA_group_joined[USA_group_joined[, Country == "Brazil"]]$TotalValue, opacity = 0.5, time = unique(USA_group_joined$Year)) %>%
leaflet.minicharts::addFlows(countries$longitude[countries$Country == "United States"], countries$latitude[countries$Country == "United States"],
countries$longitude[countries$Country == "China"], countries$latitude[countries$Country == "China"], color = 'red',
flow = USA_group_joined[USA_group_joined[, Country == "China"]]$TotalValue, opacity = 0.5, time =unique(USA_group_joined$Year)) %>%
leaflet.minicharts::addFlows(countries$longitude[countries$Country == "United States"], countries$latitude[countries$Country == "United States"],
countries$longitude[countries$Country == "Australia"], countries$latitude[countries$Country == "Australia"], color = 'orange',
flow = USA_group_joined[USA_group_joined[, Country == "Australia"]]$TotalValue, opacity = 0.5, time =unique(USA_group_joined$Year)) %>%
leaflet.minicharts::addFlows(countries$longitude[countries$Country == "United States"], countries$latitude[countries$Country == "United States"],
countries$longitude[countries$Country == "Albania"], countries$latitude[countries$Country == "Albania"], color = 'black',
flow = USA_group_joined[USA_group_joined[, Country == "Albania"]]$TotalValue, opacity = 0.5, time =unique(USA_group_joined$Year))
basemap = leaflet(USA_group_joined) %>% addTiles()
basemap %>% leaflet.minicharts::addFlows(countries$longitude[countries$Country == "United States"], countries$latitude[countries$Country == "United States"],USA_group_joined$longitude, USA_group_joined$latitude,
flow = USA_group_joined$TotalValue,
time = USA_group_joined$Year)
USA Group Joined cut to show select countries.
USA_group_joined_cut = USA_group_joined[Country %in% c("Canada", "China", "Brazil", "India", "Australia", "South Africa", "Mexico")]
Repeat the plot
basemap = leaflet(USA_group_joined_cut) %>% addTiles()
basemap %>% leaflet.minicharts::addFlows(countries$longitude[countries$Country == "United States"], countries$latitude[countries$Country == "United States"],USA_group_joined_cut$longitude, USA_group_joined_cut$latitude,
flow = USA_group_joined_cut$TotalValue,
time = USA_group_joined_cut$Year)
LS0tDQp0aXRsZTogIk1CUyBDb210cmFkZSBEYXRhIE5vdGVib29rIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KDQpMb2FkIHRoZSBsaWJyYXJpZXMuDQoNCmBgYHtyfQ0KbGlicmFyeShkYXRhLnRhYmxlKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KYGBgDQoNClRoZSBjb2RlIGJlbG93IHdpbGwgc2hvdyB0aGUgZGF0YSBjbGVhbmluZyBhbmQgZXhwbG9yYXRpb24uDQoNCkZpcnN0IGxvYWQgdGhlIGRhdGEuDQoNCiMgRGF0YSBXcmFuZ2xpbmcNCg0KYGBge3J9DQpzZXR3ZCgiQzovVXNlcnMvRmVyaGF0L0RvY3VtZW50cy9HaXRIdWIvV29ybGRCYW5rRGF0YSIpDQoNCmRhdGEgPSByZWFkLmNzdigiTUJTQ29tdHJhZGUuY3N2IikNCg0KZGF0YSRzZXJpZXNfdHlwZSA9IE5VTEwNCmRhdGEkdGFibGVfdHlwZSA9IE5VTEwNCmRhdGEkdGFibGVfdHlwZV9kZXNjID0gTlVMTA0KZGF0YSRwZXJpb2RfdHlwZSA9IE5VTEwNCmRhdGEkdHJhZGVfZmxvdyA9IE5VTEwNCmRhdGEkY3VycmVuY3lfdHlwZSA9IE5VTEwNCmRhdGEkdmFsdWVfdW5pdCA9IE5VTEwNCmRhdGEkdmFsdWVfdHlwZSA9IE5VTEwNCmRhdGEkdmFsdWVfdHlwZV9kZXNjID0gTlVMTA0KZGF0YSRiYXNlX3llYXIgPSBOVUxMDQpkYXRhJHBlcmlvZF9udW1iZXIgPSBOVUxMDQpkYXRhJGNvdW50cnlfdHlwZSA9IE5VTEwNCmRhdGEkZXN0aW1hdGlvbl90eXBlID0gTlVMTA0KZGF0YSRlc3RpbWF0aW9uX3R5cGVfZGVzYyA9IE5VTEwNCg0KDQpzYXZlKGRhdGEsIGZpbGUgPSAiY2xlYW5lZF9kYXRhLnJkYXRhIikNCmBgYA0KDQpgYGB7cn0NCmRhdGEgPSBhcy5kYXRhLnRhYmxlKGRhdGEpDQpgYGANCg0KTGV0cyBleHBsb3JlIHNvbWUgb2YgdGhlIGRhdGEuDQoNCmBgYHtyfQ0KaGVhZChkYXRhW2NvdW50cnlfZW5nbGlzaF9uYW1lID09ICJVU0EiXSwxMCkNCmBgYA0KTGV0cyBkbyBzb21lIHBsb3RzLiBCdXQgZmlyc3QgbGV0cyBnZXQgcmlkIG9mIHdvcmxkIHJlZ2lvbnMgYW5kIG9ubHkga2VlcCBjb3VudHJ5ZXMgc28gd2UgZG9uJ3QgZG91YmxlIGNvdW50LiBMZXRzIGxvb2sgYXQgdGhlIFVTQSBmaXJzdC4NCmBgYHtyfQ0KVVNBID0gZGF0YVtjb3VudHJ5X2VuZ2xpc2hfbmFtZSA9PSAiVVNBIiAmIHBhcnRuZXJfY291bnRyeV9jb2RlID4gMCAmIHBhcnRuZXJfY291bnRyeV9jb2RlIDwgODk5IF0NCmhlYWQoVVNBLDEwKQ0KYGBgDQoNCk5vdyBsZXRzIGdyb3VwICBldmVyeXRoaW5nIGJ5IHBhcnRuZXIgZXhwb3J0IGNvdW50cnkuDQpgYGB7cn0NClVTQV9ncm91cCA9IFVTQVssIC4odmFsdWUuU1VNID0gc3VtKHZhbHVlKSksIGJ5PWMoInBhcnRuZXJfY291bnRyeV9lbmdsaXNoX25hbWUiLCAieWVhciIpXQ0Kc2V0bmFtZXMoVVNBX2dyb3VwLCBjKCJDb3VudHJ5IiwiWWVhciIsICJUb3RhbFZhbHVlIikgKQ0KaGVhZChVU0FfZ3JvdXAsMTApDQpgYGANCg0KTm93IGxldHMgcGxvdC4NCg0KIyBMaW5lIGNoYXJ0DQoNCmBgYHtyfQ0KDQpsaWJyYXJ5KHBsb3RseSkNCnAgPSBnZ3Bsb3QoVVNBX2dyb3VwLCBhZXMoeCA9IFllYXIsIHk9VG90YWxWYWx1ZSkpKw0KICBnZW9tX2xpbmUoYWVzKGNvbG91ciA9IENvdW50cnkpKSsNCiAgZ2VvbV9wb2ludChhZXMoY29sb3VyID0gQ291bnRyeSksIHNpemU9MikrDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpDQoNCmdncGxvdGx5KHApDQpgYGANCiMgUGllIGNoYXJ0DQoNCmBgYHtyfQ0KZ2dwbG90KFVTQV9ncm91cCwgYWVzKHg9ZmFjdG9yKDEpLCBmaWxsID0gZmFjdG9yKENvdW50cnkpKSkrDQogIGdlb21fYmFyKGFlcyh3ZWlnaHQgPSBUb3RhbFZhbHVlKSwgd2lkdGggPSAxKSsNCiAgY29vcmRfcG9sYXIodGhldGEgPSAieSIsIHN0YXJ0PTApKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKQ0KYGBgDQoNCiMgU2Fua2V5IERpYWdyYW0NCg0KYGBge3IgIHJlc3VsdHM9J2FzaXMnfQ0KVVNBX2dyb3VwX2NvdW50cnkgPSBVU0FfZ3JvdXBbLCAuKFN1bSA9IHN1bShUb3RhbFZhbHVlKSksIGJ5PUNvdW50cnldDQpVU0FfZ3JvdXBfY291bnRyeSRTb3VyY2UgPSAiVVNBIg0KVVNBX2dyb3VwX2NvdW50cnlbLCBDb3VudHJ5Oj1hcy5jaGFyYWN0ZXIoQ291bnRyeSldDQoNClVTQV9ncm91cF9jb3VudHJ5IDwtIFVTQV9ncm91cF9jb3VudHJ5ICU+JSANCiAgc2VsZWN0KENvdW50cnksIFNvdXJjZSwgU3VtKQ0Kc2V0b3JkZXIoVVNBX2dyb3VwX2NvdW50cnksIFN1bSkNCg0Kc2xpY2UgPSB0YWlsKFVTQV9ncm91cF9jb3VudHJ5LCAxMCkNCg0Kc2xpY2UgPC0gc2xpY2UgJT4lIA0KICBzZWxlY3QoU291cmNlLCBDb3VudHJ5LCBTdW0pDQoNCmxpYnJhcnkoZ29vZ2xlVmlzKQ0Kc2sxIDwtIGd2aXNTYW5rZXkoc2xpY2UsIGZyb209IlNvdXJjZSIsIHRvPSJDb3VudHJ5Iiwgd2VpZ2h0PSJTdW0iKQ0KcHJpbnQoc2sxLCAnY2hhcnQnKQ0KYGBgDQpMZXRzIHBsYXkgd2l0aCBsZWFmbGV0IHBhY2thZ2UuDQoNCiMgTGVhZmxldA0KDQpgYGB7cn0NCmxpYnJhcnkobGVhZmxldCkNCm0gPC0gbGVhZmxldCgpICU+JSBzZXRWaWV3KGxuZyA9IC03MS4wNTg5LCBsYXQgPSA0Mi4zNjAxLCB6b29tID0gMTIpDQptICU+JSBhZGRUaWxlcygpDQpgYGANCkxldHMgZ2V0IHRoZSBsYXRpdHVkZSBhbmQgbG9uZ2l0dWRlIG9mIGNvdW50cmllcy4NCg0KYGBge3J9DQpjb3VudHJpZXMgPSByZWFkLmNzdigiY291bnRyaWVzLmNzdiIpDQpjb3VudHJpZXMgPSBhcy5kYXRhLnRhYmxlKGNvdW50cmllcykNCnNldG5hbWVzKGNvdW50cmllcywgb2xkID0gYygiY291bnRyeSIsICJuYW1lIiksIG5ldyA9IGMoIkNvdW50cnlDb2RlIiwgIkNvdW50cnkiKSkNCg0KaGVhZChjb3VudHJpZXMsMTApDQpgYGANCk5vdyBsZXRzIHBvcHVsYXRlIFVTQV9ncm91cCBkYXRhIHRhYmxlIHRoZSBsYXRpdHVkZSBhbmQgbG9uZ2l0dWRlIG9mIHRoZSBjb3VudHJpZXMuDQoNCmBgYHtyfQ0KVVNBX2dyb3VwX2pvaW5lZCA9IG1lcmdlKFVTQV9ncm91cCwgY291bnRyaWVzLCBieSA9ICJDb3VudHJ5IikNCg0KbmEub21pdChVU0FfZ3JvdXBfam9pbmVkKQ0KDQpoZWFkKFVTQV9ncm91cF9qb2luZWQsIDEwKQ0KYGBgDQoNCmBgYHtyfQ0Kc2V0b3JkZXIoVVNBX2dyb3VwX2pvaW5lZCwgQ291bnRyeSwgWWVhcikNCmxlYWZsZXQoVVNBX2dyb3VwX2pvaW5lZFtVU0FfZ3JvdXBfam9pbmVkWyxZZWFyID09IDIwMTBdXSkgJT4lIGFkZFRpbGVzKCkgJT4lDQogIGFkZENpcmNsZXMobG5nID0gfmxvbmdpdHVkZSwgbGF0ID0gfmxhdGl0dWRlLCB3ZWlnaHQgPSAxLA0KICAgIHJhZGl1cyA9IH5zcXJ0KFRvdGFsVmFsdWUpLCBwb3B1cCA9IH5wYXN0ZShDb3VudHJ5LCJWb2x1bWU6ICIsVG90YWxWYWx1ZSksIGZpbGxPcGFjaXR5ID0gMC41DQogICkNCmBgYA0KDQpOb3cgbGV0cyBsb29rIGF0IHRoZSBmbG93cyB1c2luZyBMZWFmbGV0J3MgYWRkZmxvd3MgZnVuY3Rpb24uDQoNCmBgYHtyfQ0KDQpsZWFmbGV0KFVTQV9ncm91cF9qb2luZWRbVVNBX2dyb3VwX2pvaW5lZFssWWVhciA9PSAyMDEwXV0pICU+JSBhZGRUaWxlcygpICU+JQ0KICBhZGRDaXJjbGVzKGxuZyA9IH5sb25naXR1ZGUsIGxhdCA9IH5sYXRpdHVkZSwgd2VpZ2h0ID0gMSwNCiAgICByYWRpdXMgPSB+c3FydChUb3RhbFZhbHVlKSwgcG9wdXAgPSB+cGFzdGUoQ291bnRyeSwiVm9sdW1lOiAiLFRvdGFsVmFsdWUpLCBmaWxsT3BhY2l0eSA9IDAuNQ0KICApICU+JQ0KICBsZWFmbGV0Lm1pbmljaGFydHM6OmFkZEZsb3dzKGNvdW50cmllcyRsb25naXR1ZGVbY291bnRyaWVzJENvdW50cnkgPT0gIlVuaXRlZCBTdGF0ZXMiXSwgY291bnRyaWVzJGxhdGl0dWRlW2NvdW50cmllcyRDb3VudHJ5ID09ICJVbml0ZWQgU3RhdGVzIl0sDQogICAgICAgICAgIGNvdW50cmllcyRsb25naXR1ZGVbY291bnRyaWVzJENvdW50cnkgPT0gIkJyYXppbCJdLCBjb3VudHJpZXMkbGF0aXR1ZGVbY291bnRyaWVzJENvdW50cnkgPT0gIkJyYXppbCJdLCBjb2xvciA9ICdncmVlbicsDQogICAgICAgICAgIGZsb3cgPSBVU0FfZ3JvdXBfam9pbmVkW1VTQV9ncm91cF9qb2luZWRbLFllYXIgPT0gMjAxMCAmIENvdW50cnkgPT0gIkJyYXppbCJdXSRUb3RhbFZhbHVlLCBvcGFjaXR5ID0gMC41KSAlPiUNCiAgbGVhZmxldC5taW5pY2hhcnRzOjphZGRGbG93cyhjb3VudHJpZXMkbG9uZ2l0dWRlW2NvdW50cmllcyRDb3VudHJ5ID09ICJVbml0ZWQgU3RhdGVzIl0sIGNvdW50cmllcyRsYXRpdHVkZVtjb3VudHJpZXMkQ291bnRyeSA9PSAiVW5pdGVkIFN0YXRlcyJdLA0KICAgICAgICAgICBjb3VudHJpZXMkbG9uZ2l0dWRlW2NvdW50cmllcyRDb3VudHJ5ID09ICJDaGluYSJdLCBjb3VudHJpZXMkbGF0aXR1ZGVbY291bnRyaWVzJENvdW50cnkgPT0gIkNoaW5hIl0sIGNvbG9yID0gJ3JlZCcsDQogICAgICAgICAgIGZsb3cgPSBVU0FfZ3JvdXBfam9pbmVkW1VTQV9ncm91cF9qb2luZWRbLFllYXIgPT0gMjAxMCAmIENvdW50cnkgPT0gIkNoaW5hIl1dJFRvdGFsVmFsdWUsIG9wYWNpdHkgPSAwLjUpICU+JQ0KICBsZWFmbGV0Lm1pbmljaGFydHM6OmFkZEZsb3dzKGNvdW50cmllcyRsb25naXR1ZGVbY291bnRyaWVzJENvdW50cnkgPT0gIlVuaXRlZCBTdGF0ZXMiXSwgY291bnRyaWVzJGxhdGl0dWRlW2NvdW50cmllcyRDb3VudHJ5ID09ICJVbml0ZWQgU3RhdGVzIl0sDQogICAgICAgICAgIGNvdW50cmllcyRsb25naXR1ZGVbY291bnRyaWVzJENvdW50cnkgPT0gIkF1c3RyYWxpYSJdLCBjb3VudHJpZXMkbGF0aXR1ZGVbY291bnRyaWVzJENvdW50cnkgPT0gIkF1c3RyYWxpYSJdLCBjb2xvciA9ICdvcmFuZ2UnLA0KICAgICAgICAgICBmbG93ID0gVVNBX2dyb3VwX2pvaW5lZFtVU0FfZ3JvdXBfam9pbmVkWyxZZWFyID09IDIwMTAgJiBDb3VudHJ5ID09ICJBdXN0cmFsaWEiXV0kVG90YWxWYWx1ZSwgb3BhY2l0eSA9IDAuNSkNCg0KDQpgYGANCg0KTGV0cyBkbyBpdCB3aXRoIHRpbWUNCg0KYGBge3J9DQpsZWFmbGV0KFVTQV9ncm91cF9qb2luZWQpICU+JSBhZGRUaWxlcygpICU+JQ0KICBsZWFmbGV0Lm1pbmljaGFydHM6OmFkZEZsb3dzKGNvdW50cmllcyRsb25naXR1ZGVbY291bnRyaWVzJENvdW50cnkgPT0gIlVuaXRlZCBTdGF0ZXMiXSwgY291bnRyaWVzJGxhdGl0dWRlW2NvdW50cmllcyRDb3VudHJ5ID09ICJVbml0ZWQgU3RhdGVzIl0sDQogICAgICAgICAgIGNvdW50cmllcyRsb25naXR1ZGVbY291bnRyaWVzJENvdW50cnkgPT0gIkJyYXppbCJdLCBjb3VudHJpZXMkbGF0aXR1ZGVbY291bnRyaWVzJENvdW50cnkgPT0gIkJyYXppbCJdLCBjb2xvciA9ICdncmVlbicsDQogICAgICAgICAgIGZsb3cgPSBVU0FfZ3JvdXBfam9pbmVkW1VTQV9ncm91cF9qb2luZWRbLCBDb3VudHJ5ID09ICJCcmF6aWwiXV0kVG90YWxWYWx1ZSwgb3BhY2l0eSA9IDAuNSwgdGltZSA9IHVuaXF1ZShVU0FfZ3JvdXBfam9pbmVkJFllYXIpKSAlPiUNCiAgbGVhZmxldC5taW5pY2hhcnRzOjphZGRGbG93cyhjb3VudHJpZXMkbG9uZ2l0dWRlW2NvdW50cmllcyRDb3VudHJ5ID09ICJVbml0ZWQgU3RhdGVzIl0sIGNvdW50cmllcyRsYXRpdHVkZVtjb3VudHJpZXMkQ291bnRyeSA9PSAiVW5pdGVkIFN0YXRlcyJdLA0KICAgICAgICAgICBjb3VudHJpZXMkbG9uZ2l0dWRlW2NvdW50cmllcyRDb3VudHJ5ID09ICJDaGluYSJdLCBjb3VudHJpZXMkbGF0aXR1ZGVbY291bnRyaWVzJENvdW50cnkgPT0gIkNoaW5hIl0sIGNvbG9yID0gJ3JlZCcsDQogICAgICAgICAgIGZsb3cgPSBVU0FfZ3JvdXBfam9pbmVkW1VTQV9ncm91cF9qb2luZWRbLCBDb3VudHJ5ID09ICJDaGluYSJdXSRUb3RhbFZhbHVlLCBvcGFjaXR5ID0gMC41LCB0aW1lID11bmlxdWUoVVNBX2dyb3VwX2pvaW5lZCRZZWFyKSkgJT4lDQogIGxlYWZsZXQubWluaWNoYXJ0czo6YWRkRmxvd3MoY291bnRyaWVzJGxvbmdpdHVkZVtjb3VudHJpZXMkQ291bnRyeSA9PSAiVW5pdGVkIFN0YXRlcyJdLCBjb3VudHJpZXMkbGF0aXR1ZGVbY291bnRyaWVzJENvdW50cnkgPT0gIlVuaXRlZCBTdGF0ZXMiXSwNCiAgICAgICAgICAgY291bnRyaWVzJGxvbmdpdHVkZVtjb3VudHJpZXMkQ291bnRyeSA9PSAiQXVzdHJhbGlhIl0sIGNvdW50cmllcyRsYXRpdHVkZVtjb3VudHJpZXMkQ291bnRyeSA9PSAiQXVzdHJhbGlhIl0sIGNvbG9yID0gJ29yYW5nZScsDQogICAgICAgICAgIGZsb3cgPSBVU0FfZ3JvdXBfam9pbmVkW1VTQV9ncm91cF9qb2luZWRbLCBDb3VudHJ5ID09ICJBdXN0cmFsaWEiXV0kVG90YWxWYWx1ZSwgb3BhY2l0eSA9IDAuNSwgdGltZSA9dW5pcXVlKFVTQV9ncm91cF9qb2luZWQkWWVhcikpICU+JQ0KICAgIGxlYWZsZXQubWluaWNoYXJ0czo6YWRkRmxvd3MoY291bnRyaWVzJGxvbmdpdHVkZVtjb3VudHJpZXMkQ291bnRyeSA9PSAiVW5pdGVkIFN0YXRlcyJdLCBjb3VudHJpZXMkbGF0aXR1ZGVbY291bnRyaWVzJENvdW50cnkgPT0gIlVuaXRlZCBTdGF0ZXMiXSwNCiAgICAgICAgICAgY291bnRyaWVzJGxvbmdpdHVkZVtjb3VudHJpZXMkQ291bnRyeSA9PSAiQWxiYW5pYSJdLCBjb3VudHJpZXMkbGF0aXR1ZGVbY291bnRyaWVzJENvdW50cnkgPT0gIkFsYmFuaWEiXSwgY29sb3IgPSAnYmxhY2snLA0KICAgICAgICAgICBmbG93ID0gVVNBX2dyb3VwX2pvaW5lZFtVU0FfZ3JvdXBfam9pbmVkWywgQ291bnRyeSA9PSAiQWxiYW5pYSJdXSRUb3RhbFZhbHVlLCBvcGFjaXR5ID0gMC41LCB0aW1lID11bmlxdWUoVVNBX2dyb3VwX2pvaW5lZCRZZWFyKSkNCmBgYA0KDQoNCmBgYHtyfQ0KDQpiYXNlbWFwID0gbGVhZmxldChVU0FfZ3JvdXBfam9pbmVkKSAlPiUgYWRkVGlsZXMoKQ0KDQpiYXNlbWFwICU+JSBsZWFmbGV0Lm1pbmljaGFydHM6OmFkZEZsb3dzKGNvdW50cmllcyRsb25naXR1ZGVbY291bnRyaWVzJENvdW50cnkgPT0gIlVuaXRlZCBTdGF0ZXMiXSwgY291bnRyaWVzJGxhdGl0dWRlW2NvdW50cmllcyRDb3VudHJ5ID09ICJVbml0ZWQgU3RhdGVzIl0sVVNBX2dyb3VwX2pvaW5lZCRsb25naXR1ZGUsIFVTQV9ncm91cF9qb2luZWQkbGF0aXR1ZGUsDQogICAgZmxvdyA9IFVTQV9ncm91cF9qb2luZWQkVG90YWxWYWx1ZSwNCiAgICB0aW1lID0gVVNBX2dyb3VwX2pvaW5lZCRZZWFyKQ0KYGBgDQoNClVTQSBHcm91cCBKb2luZWQgY3V0IHRvIHNob3cgc2VsZWN0IGNvdW50cmllcy4NCg0KYGBge3J9DQpVU0FfZ3JvdXBfam9pbmVkX2N1dCA9IFVTQV9ncm91cF9qb2luZWRbQ291bnRyeSAlaW4lIGMoIkNhbmFkYSIsICJDaGluYSIsICJCcmF6aWwiLCAiSW5kaWEiLCAiQXVzdHJhbGlhIiwgIlNvdXRoIEFmcmljYSIsICJNZXhpY28iKV0NCmBgYA0KDQpSZXBlYXQgdGhlIHBsb3QNCg0KYGBge3J9DQpiYXNlbWFwID0gbGVhZmxldChVU0FfZ3JvdXBfam9pbmVkX2N1dCkgJT4lIGFkZFRpbGVzKCkNCg0KYmFzZW1hcCAlPiUgbGVhZmxldC5taW5pY2hhcnRzOjphZGRGbG93cyhjb3VudHJpZXMkbG9uZ2l0dWRlW2NvdW50cmllcyRDb3VudHJ5ID09ICJVbml0ZWQgU3RhdGVzIl0sIGNvdW50cmllcyRsYXRpdHVkZVtjb3VudHJpZXMkQ291bnRyeSA9PSAiVW5pdGVkIFN0YXRlcyJdLFVTQV9ncm91cF9qb2luZWRfY3V0JGxvbmdpdHVkZSwgVVNBX2dyb3VwX2pvaW5lZF9jdXQkbGF0aXR1ZGUsDQogICAgZmxvdyA9IFVTQV9ncm91cF9qb2luZWRfY3V0JFRvdGFsVmFsdWUsDQogICAgdGltZSA9IFVTQV9ncm91cF9qb2luZWRfY3V0JFllYXIpDQpgYGANCg0K